package com.atguigu.gmall.item.config;

import com.atguigu.gmall.common.cache.GmallCacheAspect;
import com.atguigu.gmall.common.config.ItemServiceRedissonConfig;
import feign.Logger;
import lombok.Data;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.*;

/**
 * 工具类提取的所有自动配置类我们使用 @Import 即可
 * 导入自己的 GmallCacheAspect.class 分布式缓存切面
 *
 * 开启feign的追踪日志排错
 * 1、配置feign接口所在包的日志级别
 *  logging:
 *      level:
 *          com.atguigu.gmall.feign.product: debug
 *
 * 2、配置日志组件
 *     @Bean
 *     Logger.Level feignLoggerLevel() {
 *         return Logger.Level.FULL;
 *     }
 */
@Import({ItemServiceRedissonConfig.class, GmallCacheAspect.class})
//让 Spring Boot自己的RedisAutoConfiguration 配置完以后再启动我们的
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableAspectJAutoProxy  //开启切面功能
@Configuration
public class ItemConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    /**
     * int corePoolSize,      16
     * int maximumPoolSize,   32
     * long keepAliveTime,
     * TimeUnit unit,
     * BlockingQueue<Runnable> workQueue,    50
     * ThreadFactory threadFactory,
     * RejectedExecutionHandler handler
     * <p>
     * 150个线程进来
     * 1、先立即运行 16个
     * 2、接下来剩下任务进入队列  50 个 （被人拿了16以后再进16）
     * 3、拿出16个，达到运行峰值 32 个
     * 4、状态。32个再运行，50个队列等待。最终只有 82个线程被安排了。
     * 5、150-82= 68个 要被RejectedExecutionHandler抛弃
     *
     * @return
     */
    //配置自己的业务线程池 核心业务线程池
    @Bean("corePool")
    public ThreadPoolExecutor executor(ThreadConfigProperties properties) {
        return new ThreadPoolExecutor(properties.core,
                properties.max,
                properties.keepalive, //线程池 1min了都没有活要干了
                TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(properties.queueLength),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );
    }

    @Component
    @ConfigurationProperties(prefix = "item-service.thread")
    @Data
    class ThreadConfigProperties {
        private Integer core;
        private Integer max;
        private Long keepalive;
        private Integer queueLength;
    }

    class MyItemServiceThreadFactory implements ThreadFactory
    {
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName("item-service: "+ UUID.randomUUID().toString().substring(0,5));
            return thread;
        }
    }



}